/*
 * Copyright 2020-2030 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitee.minimalismstyle.fresh.common.data.beetl.dao

import com.gitee.minimalismstyle.fresh.common.core.domain.QueryBody
import com.gitee.minimalismstyle.fresh.common.core.domain.QueryParams
import com.gitee.minimalismstyle.fresh.common.core.domain.Simple
import com.gitee.minimalismstyle.fresh.common.data.beetl.ami.*
import org.beetl.sql.core.SQLManager
import org.beetl.sql.core.query.LambdaQuery
import org.beetl.sql.core.query.Query
import org.beetl.sql.mapper.annotation.AutoMapper
import org.beetl.sql.mapper.internal.*


/**
 * 基础BaseDao
 * @author maoxiaodong
 */
interface BaseDao<T, ID> {

    /**
     * 插入数据
     * @param entity 实体对象
     * @return 插入数量
     */
    @AutoMapper(InsertAMI::class)
    fun insert(entity: T): Int

    /**
     * 批量插入数据
     * @param entities 实体对象列表
     * @return 插入数量
     */
    @AutoMapper(InsertBatchAMI::class)
    fun insertAll(entities: List<T>)


    /**
     * 更新数据
     * @param entity 实体对象
     * @return 更新数量
     */
    @AutoMapper(UpdateByIdAMI::class)
    fun updateById(entity: T): Int

    /**
     * 批量更新数据
     * @param entity 实体对象
     * @return 更新数量
     */
    @AutoMapper(UpdateByIdBatchAMI::class)
    fun updateAllById(entity: List<T>): Int

    /**
     * 更新数据，只更新属性不为null的
     * @param entity 实体对象
     * @return 更新数量
     */
    @AutoMapper(UpdateTemplateByIdAMI::class)
    fun updateSelectiveById(entity: T): Int

    /**
     * 保存数据，更新和插入
     * @param entity 实体对象
     * @return 更新数量
     */
    @AutoMapper(SaveAmi::class)
    fun save(entity: T): Int

    /**
     * 保存数据
     * @param entities 实体对象列表
     * @return 插入数量
     */
    @AutoMapper(SaveAllAmi::class)
    fun saveAll(entities: List<T>): Int

    /**
     * 保存数据，更新和插入，只更新和插入属性不为null的
     * @param entity 实体对象
     * @return 更新数量
     */
    @AutoMapper(UpsertByTemplateAMI::class)
    fun saveSelective(entity: T): Int

    /**
     * 根据id删除数据
     * @param id
     * @return 删除数量
     */
    @AutoMapper(DeleteByIdAMI::class)
    fun deleteById(id: ID): Int

    /**
     * 根据多个id删除数据
     * @param ids
     * @return 删除数量
     */
    @AutoMapper(DeleteByIdsAmi::class)
    fun deleteAllById(ids: List<ID>): Int




    /**
     * 根据id逻辑删除数据
     * @param id
     * @return 删除数量
     */
    @AutoMapper(LogicDeleteByIdAmi::class)
    fun logicDeleteById(id: Any) : Int

    /**
     * 根据多个id逻辑删除数据
     * @param ids
     * @return 删除数量
     */
    @AutoMapper(LogicDeleteByIdAmi::class)
    fun logicDeleteByIds(vararg ids: Any) : Int

    /**
     * 根据id查询数据
     * @param id
     * @return 实体对象
     */
    @AutoMapper(SingleAMI::class)
    fun findById(id: ID): T

    /**
     * 根据主键获取对象，如果在事物中执行会添加数据库行级锁
     * (select * from table where id = ? for update)，如果对象不存在，返回null
     *
     * @param id
     * @return
     */
    @AutoMapper(LockAMI::class)
    fun lock(id: ID): T

    /**
     * 根据多个id查询数据
     * @param ids
     * @return 实体list对象
     */
    @AutoMapper(FindByIdsAmi::class)
    fun findAllById(ids: List<ID>): List<T>

    /**
     * 查询所有
     * @return 实体list对象
     */
    @AutoMapper(AllAMI::class)
    fun findAll(): List<T>

    /**
     * 查询指定位置的数据
     * @param start 开始位置
     * @param size 数量
     * @return 实体list对象
     */
    @AutoMapper(AllAMI::class)
    fun findAll(start: Int, size: Int): List<T>

    /**
     * 模板查询，返回符合模板得所有结果。beetlsql将取出非null值（日期类型排除在外），从数据库找出完全匹配的结果集
     *
     * @param entity
     * @return
     */
    @AutoMapper(TemplateAMI::class)
    fun findAll(entity: T): List<T>


    /**
     * 模板查询，返回一条结果,如果没有，返回null
     *
     * @param entity
     * @return
     */
    @AutoMapper(TemplateOneAMI::class)
    fun <T> find(entity: T): T

    /**
     * 符合模板得个数
     *
     * @param entity
     * @return
     */
    @AutoMapper(TemplateCountAMI::class)
    fun count(entity: T): Long

    /**
     * 统计总数
     * @return 数量
     */
    @AutoMapper(AllCountAMI::class)
    fun count(): Long

    /**
     * 判断ID存在不
     * @return
     */
    fun exist(id: ID): Boolean {
        return getSQLManager().exist(this.getType(), id)
    }

    /**
     * 验证唯一属性是否存在
     * @param entity 实体对象
     * @return
     */
    @AutoMapper(IsUniqueAmi::class)
    fun isUnique(entity: T): Boolean


    /**
     * 返回一个Query对象
     * @return
     */
    @AutoMapper(QueryAMI::class)
    fun createQuery(): Query<T>

    /**
     * 返回一个LambdaQuery对象
     * @return
     */
    @AutoMapper(LambdaQueryAMI::class)
    fun createLambdaQuery(): LambdaQuery<T>

    /**
     * 获取实体类型
     * @return 实体类型
     */
    @AutoMapper(GetTargetEntityAMI::class)
    fun getType(): Class<*>

    /**
     * 根据通用查询参数查询数据
     * @param params 通用查询参数
     * @return QueryBody对象
     */
    @AutoMapper(FindByQueryParamsAmi::class)
    fun findByQueryParams(params: QueryParams<Simple>): QueryBody<Simple>

    /**
     * 执行一个jdbc sql模板查询
     *
     * @param sql
     * @param args
     * @return
     */
    @AutoMapper(ExecuteAMI::class)
    fun execute(sql: String, vararg args: Any?): List<T>


    /**
     * 执行一个更新的jdbc sql
     *
     * @param sql
     * @param args
     * @return
     */
    @AutoMapper(ExecuteUpdateAMI::class)
    fun executeUpdate(sql: String?, vararg args: Any?): Int

    /**
     * 获取SQL管理器
     * @return SQLManager
     */
    @AutoMapper(GetSQLManagerAMI::class)
    fun getSQLManager(): SQLManager
}